import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:file_selector/file_selector.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:share_plus/share_plus.dart';
import 'package:path/path.dart' as path;
import '../models/word.dart';
import '../models/question.dart';
import '../models/note.dart';
import '../models/essay_material.dart';
import '../services/database_service.dart';
import '../services/web_database_service.dart';
import '../repositories/essay_material_repository.dart';
import '../utils/path_util.dart';
import '../utils/image_backup_util.dart';

// 备份文件名
const String backupFileName = 'backup.json';

class BackupData {
  final List<Word> words;
  final List<Question> questions;
  final List<Note> notes;
  final List<EssayMaterial> essayMaterials;
  final DateTime backupTime;

  BackupData({
    required this.words,
    required this.questions,
    required this.notes,
    required this.essayMaterials,
    required this.backupTime,
  });

  // 转换为JSON时处理图片路径为相对路径
  Map<String, dynamic> toJson() {
    // 处理问题列表，将图片路径转换为相对路径
    final List<Map<String, dynamic>> processedQuestions = questions.map((q) {
      Map<String, dynamic> questionMap = q.toMap();
      
      // 转换所有图片路径为相对路径
      questionMap['question_image_url'] = PathUtil.toRelativePath(questionMap['question_image_url']);
      questionMap['option_a_image_url'] = PathUtil.toRelativePath(questionMap['option_a_image_url']);
      questionMap['option_b_image_url'] = PathUtil.toRelativePath(questionMap['option_b_image_url']);
      questionMap['option_c_image_url'] = PathUtil.toRelativePath(questionMap['option_c_image_url']);
      questionMap['option_d_image_url'] = PathUtil.toRelativePath(questionMap['option_d_image_url']);
      questionMap['explanation_image_url'] = PathUtil.toRelativePath(questionMap['explanation_image_url']);
      
      return questionMap;
    }).toList();
    
    // 处理笔记列表，将图片路径转换为相对路径
    final List<Map<String, dynamic>> processedNotes = notes.map((n) {
      Map<String, dynamic> noteMap = n.toMap();
      noteMap['image_url'] = PathUtil.toRelativePath(noteMap['image_url']);
      return noteMap;
    }).toList();
    
    // 处理作文素材列表，将图片路径转换为相对路径
    final List<Map<String, dynamic>> processedEssayMaterials = essayMaterials.map((e) {
      Map<String, dynamic> essayMap = e.toMap();
      essayMap['image_url'] = PathUtil.toRelativePath(essayMap['image_url']);
      return essayMap;
    }).toList();
    
    return {
      'backup_time': backupTime.millisecondsSinceEpoch,
      'words': words.map((w) => w.toMap()).toList(),
      'questions': processedQuestions,
      'notes': processedNotes,
      'essay_materials': processedEssayMaterials,
    };
  }

  // 从JSON解析时处理图片路径为绝对路径
  factory BackupData.fromJson(Map<String, dynamic> json) {
    // 处理问题列表，将图片路径转换为绝对路径
    final List<Map<String, dynamic>> processedQuestions = (json['questions'] as List? ?? []).map((q) {
      // 转换为可变Map
      Map<String, dynamic> questionMap = Map<String, dynamic>.from(q);
      
      // 转换所有图片路径为绝对路径
      questionMap['question_image_url'] = PathUtil.toAbsolutePath(questionMap['question_image_url']);
      questionMap['option_a_image_url'] = PathUtil.toAbsolutePath(questionMap['option_a_image_url']);
      questionMap['option_b_image_url'] = PathUtil.toAbsolutePath(questionMap['option_b_image_url']);
      questionMap['option_c_image_url'] = PathUtil.toAbsolutePath(questionMap['option_c_image_url']);
      questionMap['option_d_image_url'] = PathUtil.toAbsolutePath(questionMap['option_d_image_url']);
      questionMap['explanation_image_url'] = PathUtil.toAbsolutePath(questionMap['explanation_image_url']);
      
      return questionMap;
    }).toList().cast<Map<String, dynamic>>();
    
    // 处理笔记列表，将图片路径转换为绝对路径
    final List<Map<String, dynamic>> processedNotes = (json['notes'] as List? ?? []).map((n) {
      Map<String, dynamic> noteMap = Map<String, dynamic>.from(n);
      noteMap['image_url'] = PathUtil.toAbsolutePath(noteMap['image_url']);
      return noteMap;
    }).toList().cast<Map<String, dynamic>>();
    
    // 处理作文素材列表，将图片路径转换为绝对路径
    final List<Map<String, dynamic>> processedEssayMaterials = (json['essay_materials'] as List? ?? []).map((e) {
      Map<String, dynamic> essayMap = Map<String, dynamic>.from(e);
      essayMap['image_url'] = PathUtil.toAbsolutePath(essayMap['image_url']);
      return essayMap;
    }).toList().cast<Map<String, dynamic>>();
    
    return BackupData(
      backupTime: DateTime.fromMillisecondsSinceEpoch(json['backup_time'] ?? DateTime.now().millisecondsSinceEpoch),
      words: (json['words'] as List? ?? []).map((w) => Word.fromMap(w)).toList(),
      questions: processedQuestions.map((q) => Question.fromMap(q)).toList(),
      notes: processedNotes.map((n) => Note.fromMap(n)).toList(),
      essayMaterials: processedEssayMaterials.map((e) => EssayMaterial.fromMap(e)).toList(),
    );
  }
}

class BackupResult {
  final bool success;
  final String? filePath;
  final String? errorMessage;
  final int totalItems;

  BackupResult({
    required this.success,
    this.filePath,
    this.errorMessage,
    this.totalItems = 0,
  });
}

class ImportResult {
  final bool success;
  final String? errorMessage;
  final int wordsImported;
  final int questionsImported;
  final int notesImported;
  final int essayMaterialsImported;

  ImportResult({
    required this.success,
    this.errorMessage,
    this.wordsImported = 0,
    this.questionsImported = 0,
    this.notesImported = 0,
    this.essayMaterialsImported = 0,
  });

  int get totalImported => wordsImported + questionsImported + notesImported + essayMaterialsImported;
}

class BackupUtil {
  static const String backupFileName = '学习宝库数据备份.json';
  
  /// 一键格式化数据（删除全部数据）
  static Future<bool> formatAllData() async {
    try {
      // 初始化数据库服务
      final databaseService = DatabaseService();
      await databaseService.init();
      
      final essayMaterialRepository = EssayMaterialRepository();

      // 清空所有数据
      await databaseService.wordRepository.deleteAllWords();
      await databaseService.questionRepository.deleteAllQuestions();
      await databaseService.noteRepository.deleteAllNotes();
      await essayMaterialRepository.deleteAllEssayMaterials();
      
      return true;
    } catch (e) {
      print('格式化数据失败: $e');
      return false;
    }
  }

  /// 一键导出所有数据
  static Future<BackupResult> exportAllData() async {
    try {
      // 初始化数据库服务
      final databaseService = DatabaseService();
      await databaseService.init();
      
      final essayMaterialRepository = EssayMaterialRepository();

      // 获取所有数据
      final words = await databaseService.wordRepository.getAllWords();
      final questions = await databaseService.questionRepository.getAllQuestions();
      final notes = await databaseService.noteRepository.getAllNotes();
      final essayMaterials = await essayMaterialRepository.getAllEssayMaterials();

      // 确定保存路径
      String? filePath;
      String? dirPath;
      
      if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) {
        // 桌面平台：保存到固定目录
        dirPath = 'D:\\000\\my-web\\学习宝库\\备份';
        final directory = Directory(dirPath);
        if (!await directory.exists()) {
          await directory.create(recursive: true);
        }
        
        // 清理旧的备份目录中的图片文件夹
        final oldImagesDir = Directory('$dirPath\\images');
        if (await oldImagesDir.exists()) {
          await oldImagesDir.delete(recursive: true);
          print('已删除旧的图片备份目录');
        }
        
        // 创建新的图片备份目录
        await Directory('$dirPath\\images').create(recursive: true);
        print('已创建新的图片备份目录');
        
        filePath = '$dirPath\\$backupFileName';
        final file = File(filePath);
        
        // 设置基础备份目录，用于相对路径转换
        PathUtil.setBaseBackupDir(dirPath);
        
        // 检查文件是否已存在
        if (await file.exists()) {
          print('备份文件已存在，将直接覆盖');
        } else {
          print('备份文件不存在，将创建新文件');
        }
        
        // 处理并复制所有图片文件到备份目录
        print('开始处理并复制图片文件...');
        await ImageBackupUtil.processAndCopyAllImages(
          questions, 
          notes, 
          essayMaterials, 
          dirPath
        );
        print('图片文件处理完成');
        
        // 创建备份数据（在设置基础备份目录后创建，确保相对路径正确）
        final backupData = BackupData(
          words: words,
          questions: questions,
          notes: notes,
          essayMaterials: essayMaterials,
          backupTime: DateTime.now(),
        );

        // 转换为JSON
        final jsonString = jsonEncode(backupData.toJson());
        
        // 写入或覆盖文件（FileMode.write模式会覆盖原有内容）
        await file.writeAsString(jsonString, encoding: utf8, mode: FileMode.write);
      } else {
        // 移动平台：先请求存储权限
        if (Platform.isAndroid) {
          // 请求读写权限
          final storageStatus = await Permission.storage.request();
          final externalStorageStatus = await Permission.manageExternalStorage.request();
          
          // 检查是否获得了必要的权限
          if (!storageStatus.isGranted) {
            return BackupResult(
              success: false,
              errorMessage: '需要存储权限才能导出数据',
            );
          }
          
          // 记录权限状态，便于调试
          print('存储权限状态: $storageStatus, 外部存储管理权限状态: $externalStorageStatus');
        }
        
        // 获取外部存储目录
        final directory = await getExternalStorageDirectory();
        if (directory != null) {
          // 确保路径与getBackupInfo方法一致
            try {
              final downloadDir = Directory('${directory.path.split('Android')[0]}Download/学习宝库/备份');
              dirPath = downloadDir.path;
              
              // 无论目录是否存在，都尝试创建它（如果已存在则不会有影响）
              await downloadDir.create(recursive: true);
              
              // 检查目录是否存在并确保有写入权限
              if (await downloadDir.exists()) {
                // 尝试在目录中创建一个临时文件来测试写入权限
                final testFile = File('${downloadDir.path}/.test_write_permission');
                try {
                  await testFile.writeAsString('test');
                  await testFile.delete(); // 测试成功后删除
                } catch (e) {
                  print('写入权限测试失败: $e');
                  // 没有写入权限，尝试重新创建目录
                  await downloadDir.delete(recursive: true);
                  await downloadDir.create(recursive: true);
                }
              } else {
                // 如果目录创建失败，抛出异常
                throw Exception('无法创建备份目录，请检查存储权限');
              }
              
              // 设置文件路径并确保路径格式正确
              filePath = '${downloadDir.path}/$backupFileName';
              print('设置备份文件路径: $filePath');
              final file = File(filePath);
              
              // 设置基础备份目录，用于相对路径转换
              PathUtil.setBaseBackupDir(dirPath);
              
              // 清理旧的备份目录中的图片文件夹
              final oldImagesDir = Directory('$dirPath/images');
              if (await oldImagesDir.exists()) {
                await oldImagesDir.delete(recursive: true);
                print('已删除旧的图片备份目录');
              }
              
              // 创建新的图片备份目录
              await Directory('$dirPath/images').create(recursive: true);
              print('已创建新的图片备份目录');
              
              // 处理并复制所有图片文件到备份目录
              print('开始处理并复制图片文件...');
              await ImageBackupUtil.processAndCopyAllImages(
                questions, 
                notes, 
                essayMaterials, 
                dirPath
              );
              print('图片文件处理完成');
              
              // 检查文件是否已存在，如果存在则直接覆盖
                // 无需删除原有文件，直接使用FileMode.write模式会覆盖原有内容
                try {
                  if (await file.exists()) {
                    print('备份文件已存在，将直接覆盖');
                  } else {
                    print('备份文件不存在，将创建新文件');
                  }
                
                // 创建备份数据（在设置基础备份目录后创建，确保相对路径正确）
                final backupData = BackupData(
                  words: words,
                  questions: questions,
                  notes: notes,
                  essayMaterials: essayMaterials,
                  backupTime: DateTime.now(),
                );

                // 转换为JSON
                final jsonString = jsonEncode(backupData.toJson());
                
                // 写入或覆盖文件
                  print('开始写入备份文件: $filePath');
                  // 确保使用最新的文件路径
                  final fileToWrite = File(filePath);
                  try {
                    // 使用IOSink方式写入文件，FileMode.write模式会覆盖原有内容
                    final sink = fileToWrite.openWrite(mode: FileMode.write);
                    sink.write(jsonString);
                    await sink.flush();
                    await sink.close();
                    print('成功写入备份文件');
                  } catch (writeError) {
                    print('使用IOSink写入文件失败: $writeError');
                    // 尝试使用备用方法，同样会覆盖原有内容
                    await fileToWrite.writeAsString(jsonString, encoding: utf8, mode: FileMode.write);
                  }
               } catch (e) {
                 print('写入备份文件失败: $e');
                 throw Exception('写入备份文件失败: $e');
               }
          } catch (e) {
            return BackupResult(
              success: false,
              errorMessage: '创建备份目录或写入文件失败: $e',
            );
          }
        }
      }

      final totalItems = words.length + questions.length + notes.length + essayMaterials.length;
      
      return BackupResult(
        success: true,
        filePath: filePath,
        totalItems: totalItems,
      );
    } catch (e) {
      return BackupResult(
        success: false,
        errorMessage: '导出失败: $e',
      );
    }
  }

  /// 一键导入所有数据
  static Future<ImportResult> importAllData() async {
    try {
      // 选择备份文件
      const typeGroup = XTypeGroup(
        label: 'JSON文件',
        extensions: ['json'],
      );
      
      final file = await openFile(acceptedTypeGroups: [typeGroup]);
      if (file == null) {
        return ImportResult(
          success: false,
          errorMessage: '未选择文件',
        );
      }

      // 读取文件内容
      // 使用readAsBytes读取原始字节，以便处理可能存在的BOM标记
      String jsonString;
      try {
        if (kIsWeb) {
          // Web平台处理
          final webFile = file as XFile;
          final bytes = await webFile.readAsBytes();
          
          // 检查并处理UTF-8 BOM标记（EF BB BF）
          if (bytes.length >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) {
            // 如果存在BOM，跳过前3个字节
            jsonString = utf8.decode(bytes.sublist(3));
            print('检测到BOM标记，已处理');
          } else {
            // 没有BOM，直接解码
            jsonString = utf8.decode(bytes);
          }
        } else {
          // 非Web平台处理
          final bytes = await file.readAsBytes();
          
          // 检查并处理UTF-8 BOM标记（EF BB BF）
          if (bytes.length >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) {
            // 如果存在BOM，跳过前3个字节
            jsonString = utf8.decode(bytes.sublist(3));
            print('检测到BOM标记，已处理');
          } else {
            // 没有BOM，直接解码
            jsonString = utf8.decode(bytes);
          }
        }
      } catch (e) {
        print('读取文件失败: $e');
        return ImportResult(
          success: false,
          errorMessage: '读取文件失败: $e',
        );
      }
      
      final jsonData = jsonDecode(jsonString) as Map<String, dynamic>;
      
      // 设置基础备份目录
      String? baseDir;
      String? appDir;
      
      // 获取应用文档目录，用于存储导入的图片
      final appDocDir = await getApplicationDocumentsDirectory();
      appDir = appDocDir.path;
      
      if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) {
        // 桌面平台：使用固定目录
        baseDir = 'D:\\000\\my-web\\学习宝库\\备份';
      } else {
        // 移动平台：使用外部存储目录
        final directory = await getExternalStorageDirectory();
        if (directory != null) {
          final downloadDir = '${directory.path.split('Android')[0]}Download/学习宝库/备份';
          baseDir = downloadDir;
        }
      }
      
      // 设置基础备份目录，用于相对路径转换
      if (baseDir != null) {
        PathUtil.setBaseBackupDir(baseDir);
        print('设置基础备份目录: $baseDir');
      }
      
      // 解析备份数据
      final backupData = BackupData.fromJson(jsonData);
      
      // 从备份目录复制图片文件到应用目录
      if (baseDir != null && appDir != null) {
        print('开始从备份目录恢复图片文件...');
        await ImageBackupUtil.restoreAllImagesFromBackup(
          backupData.questions,
          backupData.notes,
          backupData.essayMaterials,
          baseDir,
          appDir
        );
        print('图片文件恢复完成');
      }
      
      // 初始化数据库服务
      final databaseService = DatabaseService();
      await databaseService.init();
      
      final essayMaterialRepository = EssayMaterialRepository();

      int wordsImported = 0;
      int questionsImported = 0;
      int notesImported = 0;
      int essayMaterialsImported = 0;

      // 导入单词
      for (final word in backupData.words) {
        try {
          final wordWithoutId = Word(
            word: word.word,
            translation: word.translation,
            pronunciation: word.pronunciation,
            meaning: word.meaning,
            example: word.example,
            note: word.note,
            category: word.category,
            difficulty: word.difficulty,
            createdAt: word.createdAt,
            lastReviewedAt: word.lastReviewedAt,
            memoryStrength: word.memoryStrength,
          );
          await databaseService.wordRepository.addWord(wordWithoutId);
          wordsImported++;
        } catch (e) {
          print('导入单词失败: ${word.word}, 错误: $e');
        }
      }

      // 导入题目
      for (final question in backupData.questions) {
        try {
          final questionWithoutId = Question(
            question: question.question,
            questionImageUrl: question.questionImageUrl,
            optionA: question.optionA,
            optionAImageUrl: question.optionAImageUrl,
            optionB: question.optionB,
            optionBImageUrl: question.optionBImageUrl,
            optionC: question.optionC,
            optionCImageUrl: question.optionCImageUrl,
            optionD: question.optionD,
            optionDImageUrl: question.optionDImageUrl,
            correctAnswer: question.correctAnswer,
            explanation: question.explanation,
            explanationImageUrl: question.explanationImageUrl,
            category: question.category,
            keyPoint: question.keyPoint,
            difficulty: question.difficulty,
            tags: question.tags,
            created_at: question.created_at,
            updated_at: question.updated_at,
            type: question.type,
          );
          await databaseService.questionRepository.addQuestion(questionWithoutId);
          questionsImported++;
        } catch (e) {
          print('导入题目失败: ${question.question}, 错误: $e');
        }
      }

      // 导入笔记
      for (final note in backupData.notes) {
        try {
          final noteWithoutId = Note(
            title: note.title,
            content: note.content,
            category: note.category,
            tags: note.tags,
            imageUrl: note.imageUrl,
            created_at: note.created_at,
            updated_at: note.updated_at,
          );
          await databaseService.noteRepository.addNote(noteWithoutId);
          notesImported++;
        } catch (e) {
          print('导入笔记失败: ${note.title}, 错误: $e');
        }
      }

      // 导入作文素材
      for (final material in backupData.essayMaterials) {
        try {
          final materialWithoutId = EssayMaterial(
            title: material.title,
            content: material.content,
            category: material.category,
            tags: material.tags,
            source: material.source,
            imageUrl: material.imageUrl,
            createdAt: material.createdAt,
            updatedAt: material.updatedAt,
          );
          await essayMaterialRepository.addEssayMaterial(materialWithoutId);
          essayMaterialsImported++;
        } catch (e) {
          print('导入作文素材失败: ${material.title}, 错误: $e');
        }
      }

      return ImportResult(
        success: true,
        wordsImported: wordsImported,
        questionsImported: questionsImported,
        notesImported: notesImported,
        essayMaterialsImported: essayMaterialsImported,
      );
    } catch (e) {
      return ImportResult(
        success: false,
        errorMessage: '导入失败: $e',
      );
    }
  }

  /// 获取备份文件信息
  static Future<Map<String, dynamic>?> getBackupInfo() async {
    try {
      String? filePath;
      
      if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) {
        filePath = 'D:\\000\\my-web\\学习宝库\\备份\\$backupFileName';
      } else {
        // 移动平台：先请求存储权限
        if (Platform.isAndroid) {
          // 请求读写权限
          final storageStatus = await Permission.storage.request();
          final externalStorageStatus = await Permission.manageExternalStorage.request();
          
          // 检查是否获得了必要的权限
          if (!storageStatus.isGranted) {
            print('获取存储权限失败');
            return null; // 没有权限，返回null
          }
          
          // 记录权限状态，便于调试
          print('获取备份信息 - 存储权限状态: $storageStatus, 外部存储管理权限状态: $externalStorageStatus');
        }
        
        try {
          final directory = await getExternalStorageDirectory();
          if (directory != null) {
            // 检查备份目录是否存在且可访问
            final backupDir = Directory('${directory.path.split('Android')[0]}Download/学习宝库/备份');
            
            // 无论目录是否存在，都尝试创建它（如果已存在则不会有影响）
            try {
              await backupDir.create(recursive: true);
              
              // 再次检查目录是否成功创建
              if (!await backupDir.exists()) {
                print('无法创建备份目录');
                return null;
              }
            } catch (e) {
              print('创建备份目录失败: $e');
              return null;
            }
            
            filePath = '${backupDir.path}/$backupFileName';
          }
        } catch (e) {
          print('获取存储目录失败: $e');
          return null;
        }
      }
      
      if (filePath == null) {
        return null;
      }
      
      try {
          final file = File(filePath);
          if (!await file.exists()) {
            print('备份文件不存在: $filePath');
            return null;
          }
          
          // 检查文件是否可读
          Map<String, dynamic> jsonData;
          DateTime backupTime;
          List<dynamic> words, questions, notes, essayMaterials;
          int fileSize;
          
          try {
            // 检查文件状态
            final stat = await file.stat();
            fileSize = stat.size;
            
            if (fileSize == 0) {
              print('备份文件大小为0，可能已损坏');
              return null;
            }
            
            // 尝试读取文件内容
            String jsonString;
            try {
              // 使用readAsBytes读取原始字节，以便处理可能存在的BOM标记
              final bytes = await file.readAsBytes();
              
              // 检查并处理UTF-8 BOM标记（EF BB BF）
              if (bytes.length >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) {
                // 如果存在BOM，跳过前3个字节
                jsonString = utf8.decode(bytes.sublist(3));
                print('检测到BOM标记，已处理');
              } else {
                // 没有BOM，直接解码
                jsonString = utf8.decode(bytes);
              }
            } catch (readError) {
              print('读取备份文件失败: $readError');
              return null;
            }
            
            // 尝试解析JSON
            try {
              jsonData = jsonDecode(jsonString) as Map<String, dynamic>;
            } catch (jsonError) {
              print('解析备份文件JSON失败: $jsonError');
              return null;
            }
            
            final backupData = BackupData.fromJson(jsonData);
          
          return {
            'file_path': filePath,
            'file_size': stat.size,
            'backup_time': backupData.backupTime,
            'words_count': backupData.words.length,
            'questions_count': backupData.questions.length,
            'notes_count': backupData.notes.length,
            'essay_materials_count': backupData.essayMaterials.length,
            'total_items': backupData.words.length + backupData.questions.length + 
                          backupData.notes.length + backupData.essayMaterials.length,
          };
        } catch (e) {
          print('读取或解析备份文件失败: $e');
          return null;
        }
      } catch (e) {
        return null;
      }
    } catch (e) {
      print('获取备份信息时发生错误: $e');
      return null;
    }
  }
}